//
//  TextureMixtureImageView.m
//  OpenGL_混合
//
//  Created by user on 2018/11/5.
//  Copyright © 2018年 陈振旭. All rights reserved.
//

#import "TextureMixtureImageView.h"

#import <OpenGLES/ES2/gl.h>


//前三个是顶点坐标(x,y,z)， 后面两个是纹理坐标(s,t)
static GLfloat vertices[] =
{
    1.0f, -1.0f, -1.0f,   1.0f, 0.0f,  //右下
    -1.0f, 1.0f, -1.0f,   0.0f, 1.0f,  //左上
    -1.0f, -1.0f, -1.0f,  0.0f, 0.0f,  //左下
    1.0f, 1.0f, -1.0f,   1.0f, 1.0f,  //右上
    -1.0f, 1.0f, -1.0f,   0.0f, 1.0f,  //左上
    1.0f, -1.0f, -1.0f,   1.0f, 0.0f,  //右下
};

//顶点着色器的文件名
static NSString * const kVertexFileName = @"vertex";
//片段着色器的文件名
static NSString * const kFragmentFileName = @"fragment";

@interface TextureMixtureImageView() {
    
    GLuint _colorRenderBuffer;
    GLuint _colorFrameBuffer;
    
    GLuint _rotate;
    GLuint _positionSlot;
    float timeCount;
    GLuint _texture1;
    
    GLuint _texture2;
    
    GLuint color1;
    GLuint color2;
}

@property (nonatomic, strong) EAGLContext *context;
@property (nonatomic, strong) CAEAGLLayer *eaglayer;

@end

@implementation TextureMixtureImageView

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self setupLayer];
        [self setupContext];
        
        [self setupFrameBuffer];
        [self setupRenderBuffer];
        GLuint shader = [self compileShader];
        [self setupValueForShader:shader];
        _texture1 = [self setupTexture:@"grass.png"];
        _texture2 = [self setupTexture:@"window.png"]; 
        [self render];
        
    }
    return self;
}

+ (Class)layerClass {
    return [CAEAGLLayer class];
}


/**
 想要显示OpenGL的内容，你需要把它缺省的layer设置为一个特殊的layer。（CAEAGLLayer）。
 这里通过直接复写layerClass的方法。
 */
- (void)setupLayer {
    _eaglayer = (CAEAGLLayer *)self.layer;
    
    //设置放大倍数
    [self setContentScaleFactor:[[UIScreen mainScreen] scale]];
    
    // CALayer 默认是透明的，必须将它设为不透明才能让其可见(CALayer是透明的。而透明的层对性能负荷很大，特别是OpenGL的层。)
    _eaglayer.opaque = YES;
    
    // 设置描绘属性，在这里设置不维持渲染内容以及颜色格式为 RGBA8
    self.eaglayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        @(NO), kEAGLDrawablePropertyRetainedBacking,
                                        kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
    
}

/**
 设置OpenGL 上下文环境
 */
- (void)setupContext{
    
    self.context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
    if (!self.context) {
        NSLog(@"Failed to initialize OpenGLES 2.0 context");
        exit(1);
    }
    
    //设置为当前上下文
    if (![EAGLContext setCurrentContext:self.context]) {
        NSLog(@"Failed to set current OpenGL context");
        exit(1);
    }
}


/**
 设置渲染缓存区
 */
- (void)setupRenderBuffer {
    GLuint buffer;
    glGenRenderbuffers(1, &buffer);
    
    _colorRenderBuffer = buffer;
    
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
    
    
    //分配内存空间
    [self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.eaglayer];
    
    //将 _colorRenderBuffer 装配到 GL_COLOR_ATTACHMENT0 这个装配点上
    glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                              GL_COLOR_ATTACHMENT0,
                              GL_RENDERBUFFER,
                              _colorRenderBuffer);
}

/**
 设置帧缓存区
 */
- (void)setupFrameBuffer {
    GLuint frame;
    glGenFramebuffers(1, &frame);
    
    _colorFrameBuffer = frame;
    
    glBindFramebuffer(GL_FRAMEBUFFER, _colorFrameBuffer);
    
    
}

/**
 * 为编译好的着色器中的顶点、纹理坐标和旋转矩阵赋值
 *
 **/
- (void)setupValueForShader:(GLuint)shader{
    
    //将顶点数据拷贝到GPU
    GLuint verticesBuffer;
    glGenBuffers(1, &verticesBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, verticesBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
    
    
    
    //设置position值
    GLuint position = glGetAttribLocation(shader, "position");
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, NULL);
    glEnableVertexAttribArray(position);
    
    //设置textCoordinate值
    GLuint textCoor = glGetAttribLocation(shader, "textCoordinate");
    glVertexAttribPointer(textCoor, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (float *)NULL + 3);
    glEnableVertexAttribArray(textCoor);
    
    
    color1 = glGetUniformLocation(shader, "colorMap");
    color2 = glGetUniformLocation(shader, "colorMap2");
    
    glUniform1i(color1, 0);
    glUniform1i(color2, 1);
    
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}


/**
 渲染，最后一步
 */
- (void)render {
    
    //清屏
    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    
    CGFloat scale = [[UIScreen mainScreen] scale]; //获取视图放大倍数，可以把scale设置为1试试
    glViewport(self.frame.origin.x * scale, self.frame.origin.y * scale, self.frame.size.width * scale, self.frame.size.height * scale); //设置视口大小
    
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _texture1);
    
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, _texture2);
    
    
    glDrawArrays(GL_TRIANGLES, 0, 6);  //6是顶点的数量
    
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}


/**
 设置纹理
 */
- (GLuint)setupTexture:(NSString *)fileName{
    
    // 1、使用CoreGraphics把图像转换成bitmap data
    // 获取图片的CGImageRef
    CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
    if (!spriteImage) {
        NSLog(@"Failed to load image %@", fileName);
        exit(1);
    }
    
    // 读取图片的大小
    size_t width = CGImageGetWidth(spriteImage);
    size_t height = CGImageGetHeight(spriteImage);
    
    GLubyte * spriteData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte)); //rgba共4个byte
    
    CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4,
                                                       CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
    //在CGContextRef上绘图
    CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
    CGContextRelease(spriteContext);
    
    // 2、设置纹理环绕和过滤方式，加载图片形成纹理
    
    GLuint texture;
    glGenBuffers(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    
    //纹理环绕
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);   //超出纹理坐标s轴的部分，会重复纹理坐标的边缘，产生一种边缘被拉伸的效果
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);   //超出纹理坐标t轴的部分，会重复纹理坐标的边缘，产生一种边缘被拉伸的效果
    
    //纹理过滤
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );   //纹理缩小，采用邻近过滤(GL_NEAREST)
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );   //纹理放大，采用线性过滤(GL_LINEAR)
    
    float fw = width, fh = height;
    //加载图片形成纹理
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
    glGenerateMipmap(GL_TEXTURE_2D);
    
    
    free(spriteData);
    return texture;
}

/**
 *  glsl的编译过程主要有glCompileShader、glAttachShader、glLinkProgram三步；
 *
 *  @return 编译成功的shaders
 */
- (GLuint)compileShader {
    
    GLuint verShader, fragShader;
    GLint program = glCreateProgram();
    
    //1、编译shader
    NSString* vertFilePath = [[NSBundle mainBundle] pathForResource:kVertexFileName ofType:@"glsl"];
    [self compileShader:&verShader type:GL_VERTEX_SHADER file:vertFilePath];
    
    NSString* fragFilePath = [[NSBundle mainBundle] pathForResource:kFragmentFileName ofType:@"glsl"];
    [self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragFilePath];
    
    glAttachShader(program, verShader);
    glAttachShader(program, fragShader);
    
    //2、链接
    glLinkProgram(program);
    GLint linkSuccess;
    glGetProgramiv(program, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE) { //连接错误
        GLchar messages[256];
        glGetProgramInfoLog(program, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"error%@", messageString);
        return 0;
    }
    else {
        NSLog(@"link ok");
        glUseProgram(program); //激活着色器，成功便使用，避免由于未使用导致的的bug
    }
    
    //3、释放不需要的shader
    glDeleteShader(verShader);
    glDeleteShader(fragShader);
    
    return program;
}

/**
 编译shader功能函数
 */
- (void)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file {
    //读取字符串
    NSString* content = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];
    const GLchar* source = (GLchar *)[content UTF8String];
    
    *shader = glCreateShader(type);
    glShaderSource(*shader, 1, &source, NULL);
    glCompileShader(*shader);
    
    GLint compileSuccess;
    glGetShaderiv(*shader, GL_COMPILE_STATUS, &compileSuccess);
    if (compileSuccess == GL_FALSE) {
        GLchar messages[256];
        glGetShaderInfoLog(*shader, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    }
}
@end
